﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace FileToVideo.Helpers
{
    /// <summary>
    /// 颜色生成器
    /// </summary>
    public class ColorGenerator
    {
        /// <summary>
        /// 颜色数量
        /// </summary>
        private int count;

        /// <summary>
        /// 存储已生成的颜色列表
        /// </summary>
        private List<Color> _generatedColors = new List<Color>();

        /// <summary>
        /// 构造一个颜色生成器实例
        /// </summary>
        /// <param name="count"></param>
        /// <exception cref="ArgumentException"></exception>
        public ColorGenerator(int count)
        {
            this.count = count;
            _generatedColors = new List<Color>();

            if (count <= 0)
                throw new ArgumentException("Count must be greater than zero.");

            // 对于少量颜色，使用预定义的差异明显的颜色
            if (count <= 12)
            {
                _generatedColors = GetPredefinedColors(count);
            }

            // 对于大量颜色，使用HSL颜色空间均匀分布
            _generatedColors = GenerateHslColors(count);
        }

        /// <summary>
        /// 生成一组视觉差异明显的颜色
        /// </summary>
        /// <param name="count">需要生成的颜色数量</param>
        /// <returns>生成的颜色列表</returns>
        public static List<Color> GenerateDistinctColors(int count)
        {
            var colors = new List<Color>();

            if (count <= 0)
                return colors;

            // 对于少量颜色，使用预定义的差异明显的颜色
            if (count <= 12)
            {
                return GetPredefinedColors(count);
            }

            // 对于大量颜色，使用HSL颜色空间均匀分布
            return GenerateHslColors(count);
        }

        /// <summary>
        /// 获取预定义的颜色（最多12种差异明显的颜色）
        /// </summary>
        private static List<Color> GetPredefinedColors(int count)
        {
            var predefined = new List<Color>
            {
                Color.FromArgb(230, 25, 75),     // 红色
                Color.FromArgb(60, 180, 75),     // 绿色
                Color.FromArgb(0, 130, 200),     // 蓝色
                Color.FromArgb(245, 130, 48),    // 橙色
                Color.FromArgb(145, 30, 180),    // 紫色
                Color.FromArgb(70, 240, 240),    // 青色
                Color.FromArgb(240, 50, 230),    // 洋红色
                Color.FromArgb(210, 245, 60),    // 黄绿色
                Color.FromArgb(250, 190, 190),   // 粉红色
                Color.FromArgb(0, 128, 128),     // 深青色
                Color.FromArgb(230, 190, 255),   // 淡紫色
                Color.FromArgb(170, 110, 40)     // 棕色
            };

            return predefined.GetRange(0, Math.Min(count, predefined.Count));
        }

        /// <summary>
        /// 使用HSL颜色空间生成均匀分布的颜色
        /// </summary>
        private static List<Color> GenerateHslColors(int count)
        {
            var colors = new List<Color>();
            double goldenRatio = 0.618033988749895; // 黄金比例

            // 初始饱和度(60-100%)和亮度(60-80%)，确保颜色鲜艳但不刺眼
            double s = 0.6 + 0.4 * 0.5; // 80%
            double l = 0.6 + 0.2 * 0.5; // 70%

            for (int i = 0; i < count; i++)
            {
                // 使用黄金比例确保色相均匀分布
                double h = (i * goldenRatio) % 1.0;

                // 转换为RGB颜色
                colors.Add(HslToRgb(h, s, l));

                // 轻微调整饱和度和亮度，增加多样性
                s = 0.6 + 0.4 * ((i * 0.3) % 1.0);
                l = 0.6 + 0.2 * ((i * 0.7) % 1.0);
            }

            return colors;
        }

        /// <summary>
        /// 将HSL颜色值转换为RGB颜色
        /// </summary>
        private static Color HslToRgb(double h, double s, double l)
        {
            double r, g, b;

            if (s == 0)
            {
                r = g = b = l; // 灰色
            }
            else
            {
                double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
                double p = 2 * l - q;

                r = HueToRgb(p, q, h + 1.0 / 3);
                g = HueToRgb(p, q, h);
                b = HueToRgb(p, q, h - 1.0 / 3);
            }

            return Color.FromArgb(
                (int)(r * 255),
                (int)(g * 255),
                (int)(b * 255)
            );
        }

        /// <summary>
        /// 将色相值转换为RGB分量
        /// </summary>
        private static double HueToRgb(double p, double q, double t)
        {
            if (t < 0) t += 1;
            if (t > 1) t -= 1;

            if (t < 1.0 / 6) return p + (q - p) * 6 * t;
            if (t < 1.0 / 2) return q;
            if (t < 2.0 / 3) return p + (q - p) * (2.0 / 3 - t) * 6;

            return p;
        }

        /// <summary>
        /// 猜测输入颜色最接近已生成的哪种颜色
        /// </summary>
        /// <param name="inputColor">输入颜色（支持Color对象或#xxxxxx格式字符串）</param>
        /// <returns>最接近的已生成颜色</returns>
        public Color GuessClosestColor(object inputColor)
        {
            if (_generatedColors == null || _generatedColors.Count == 0)
            {
                throw new InvalidOperationException("尚未生成任何颜色");
            }

            Color targetColor;

            // 处理不同类型的输入
            if (inputColor is Color)
            {
                targetColor = (Color)inputColor;
            }
            else if (inputColor is string)
            {
                string colorStr = (string)inputColor;
                if (colorStr.StartsWith("#"))
                {
                    targetColor = ColorTranslator.FromHtml(colorStr);
                }
                else
                {
                    throw new ArgumentException("字符串格式的颜色必须以#开头，例如#FF0000");
                }
            }
            else
            {
                throw new ArgumentException("输入必须是Color对象或#xxxxxx格式的字符串");
            }

            // 使用CIE76色差公式计算颜色差异
            double minDistance = double.MaxValue;
            Color closestColor = _generatedColors[0];

            // 预先计算目标颜色的Lab值
            var targetLab = RgbToLab(targetColor);

            foreach (var color in _generatedColors)
            {
                // 计算Lab颜色空间中的距离
                var colorLab = RgbToLab(color);
                double distance = CalculateCie76Distance(targetLab, colorLab);

                if (distance < minDistance)
                {
                    minDistance = distance;
                    closestColor = color;
                }
            }

            return closestColor;
        }

        /// <summary>
        /// 使用CIE76公式计算Lab颜色空间中的距离
        /// </summary>
        private static double CalculateCie76Distance(LabColor lab1, LabColor lab2)
        {
            double deltaL = lab1.L - lab2.L;
            double deltaA = lab1.A - lab2.A;
            double deltaB = lab1.B - lab2.B;

            return Math.Sqrt(deltaL * deltaL + deltaA * deltaA + deltaB * deltaB);
        }

        /// <summary>
        /// 将RGB颜色转换为Lab颜色空间
        /// </summary>
        private static LabColor RgbToLab(Color color)
        {
            // 首先转换为XYZ颜色空间
            double r = color.R / 255.0;
            double g = color.G / 255.0;
            double b = color.B / 255.0;

            // 应用伽马校正
            r = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
            g = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
            b = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : b / 12.92;

            // 转换为XYZ
            double x = (r * 0.4124 + g * 0.3576 + b * 0.1805) * 100;
            double y = (r * 0.2126 + g * 0.7152 + b * 0.0722) * 100;
            double z = (r * 0.0193 + g * 0.1192 + b * 0.9505) * 100;

            // 使用D65标准光源
            x /= 95.047;
            y /= 100.000;
            z /= 108.883;

            // 转换为Lab
            x = (x > 0.008856) ? Math.Pow(x, 1.0 / 3) : (7.787 * x) + 16.0 / 116;
            y = (y > 0.008856) ? Math.Pow(y, 1.0 / 3) : (7.787 * y) + 16.0 / 116;
            z = (z > 0.008856) ? Math.Pow(z, 1.0 / 3) : (7.787 * z) + 16.0 / 116;

            return new LabColor
            {
                L = (116 * y) - 16,
                A = 500 * (x - y),
                B = 200 * (y - z)
            };
        }

        /// <summary>
        /// Lab颜色空间结构
        /// </summary>
        private struct LabColor
        {
            public double L { get; set; } // 亮度
            public double A { get; set; } // 红绿轴
            public double B { get; set; } // 黄蓝轴
        }

        /// <summary>
        /// 允许外部获取已生成的颜色列表
        /// </summary>
        public List<Color> GeneratedColors
        {
            get { return _generatedColors; }
        }
    }
}